//
//  MEFlickrPhoto.m
//  FlickrImport
//
//  Created by Sandeep Chayapathi on 1/18/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "MEFlickrPhoto.h"
#import "MEFlickrConnection.h"

@implementation MEFlickrPhoto

- (id) init {
    self = [super init];
    
    return self;
}

- (id) initWithDictionary: (NSDictionary *) dict {
    self = [super init];
    element = [dict copy];
    
    [self setPhotoId:[dict valueForKey:@"_id"]];
    [self setOwner:[dict valueForKey:@"_owner"]];
    [self setSecret: [dict valueForKey:@"_secret"]];
    [self setServer: [dict valueForKey:@"_server"]];
    [self setTitle: [dict valueForKey: @"_title"]];
    [self setIsFamily: [[dict valueForKey: @"_isfamily"] intValue]];
    [self setIsPublic: [[dict valueForKey: @"_ispublic"] intValue]];
    [self setIsFriend: [[dict valueForKey: @"_isfriend"] intValue]];
    
    originalSecret = [dict valueForKey:@"_originalsecret"];
    
    return self;
}

- (void) dealloc {
    [photoId release];
    [owner release];
    [server release];
    [secret release];
    [title release];
    [exif release];
    
    [super dealloc];
}

// Getters and Setters
- (NSDictionary *) exif; {
    return exif;
}

- (void) setExif: (NSDictionary *) tmp;{
    tmp = [tmp copy];
    [exif release];
    exif = tmp;
}

- (NSString *) photoId; {
    return photoId;
}
- (void) setPhotoId: (NSString *) tmp; {
    tmp = [tmp copy];
    [photoId release];
    photoId = tmp;
}

- (NSString *) owner; {
    return owner;
}

- (void) setOwner: (NSString *) tmp; {
    tmp = [tmp copy];
    [owner release];
    owner = tmp;
}

- (NSString *) secret; {
    return secret;
}

- (void) setSecret: (NSString *) tmp; {
    tmp = [tmp copy];
    [secret release];
    secret = tmp;
}

- (NSString *) server; {
    return server;
}

- (void) setServer: (NSString *) tmp; {
    tmp = [tmp copy];
    [server release];
    server = tmp;
}

- (NSString *) title; {
    return title;
}

- (void) setTitle: (NSString *) tmp; {
    tmp = [tmp copy];
    [title release];
    title = tmp;
}

- (int) isFamily; {
    return isFamily;
}

- (void) setIsFamily: (int) tmp; {
    isFamily = tmp;
}

- (int) isPublic; {
    return isPublic;
}

- (void) setIsPublic: (int) tmp; {
    isPublic = tmp;
}

- (int) isFriend; {
    return isFriend;
}

- (void) setIsFriend: (int) tmp; {
    isFriend = tmp;
}

- (NSString *) originalSecret; {
    return originalSecret;
}

- (NSString *) downloadPath; {
    return downloadPath;
}

- (void) downloadPath: (NSString *) tmp; {
    downloadPath = tmp;
}

- (NSString *) getURL; {
    MEFlickrConnection *conn = [MEFlickrConnection getConnectionWithDelegate: self];
    OFFlickrContext *context = [conn context];
/*
    return [context photoURLFromDictionary: element 
                                      size:@"b"];
 */
    return [context photoURLFromID: [self photoId]
                                        serverID: [self server]
                                          secret: [self secret]
                                            size: nil
                                            type: nil ];
}

- (void) downloadPhotoTo: (NSString *) directory; {
    NSURL *url = [NSURL URLWithString: [self getURL]];
    NSURLRequest *theRequest = [NSURLRequest requestWithURL: url];
    NSURLDownload  *theDownload=[[NSURLDownload alloc] initWithRequest:theRequest
                                                              delegate:self];
    
    NSString *destination = [directory stringByAppendingPathComponent:[[url path] lastPathComponent]];
    NSLog(@"going to download from %@ to %@", [self getURL], destination);
    
    if(theDownload){
        [self downloadPath: destination];
        [theDownload setDestination:destination allowOverwrite:YES];
    }else{
        NSLog(@"could not get NSURLDowload");
    }
}

- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error

{
    
    // release the connection
    
    [download release];
    
    // inform the user
    
    NSLog(@"Download failed! Error - %@ %@",
          
          [error localizedDescription],
          
          [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
    
}



- (void)downloadDidFinish:(NSURLDownload *)download {
    // release the connection
    [download release];
    
    // add exif data
    [self addExifData];
    
    // do something with the data
    NSString *path = [[NSBundle mainBundle] pathForResource:@"addPhoto" ofType:@"scpt"];
    NSURL* url = [NSURL fileURLWithPath:path];
    NSDictionary* errors = [NSDictionary dictionary];
    
    NSAppleScript* appleScript =
        [[NSAppleScript alloc] initWithContentsOfURL:url error:&errors];    
    
    // create the first parameter
    NSAppleEventDescriptor* firstParameter =
        [NSAppleEventDescriptor descriptorWithString:[self downloadPath]];    
    
    // create and populate the list of parameters (in our case just one)
    NSAppleEventDescriptor* parameters = [NSAppleEventDescriptor listDescriptor];
    [parameters insertDescriptor:firstParameter atIndex:1];    
    
    NSAppleEventDescriptor* handler =
        [NSAppleEventDescriptor descriptorWithString:
            [@"photo_import" lowercaseString]];    

    // create the AppleEvent target
    ProcessSerialNumber psn = {0, kCurrentProcess};
    NSAppleEventDescriptor* target =
        [NSAppleEventDescriptor
                        descriptorWithDescriptorType:typeProcessSerialNumber
                                               bytes:&psn
                                              length:sizeof(ProcessSerialNumber)];
    
    // create the event for an AppleScript subroutine,
    // set the method name and the list of parameters
    NSAppleEventDescriptor* event =
        [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite
                                                 eventID:kASSubroutineEvent
                                        targetDescriptor:target
                                                returnID:kAutoGenerateReturnID
                                           transactionID:kAnyTransactionID];
    [event setParamDescriptor:handler forKeyword:keyASSubroutineName];
    [event setParamDescriptor:parameters forKeyword:keyDirectObject];
    
    // call the event in AppleScript
    if (![appleScript executeAppleEvent:event error:&errors]);
    {
        // report any errors from 'errors'
    }
    
    [appleScript release];
    
    NSLog(@"downloaded: %@",[[download request] URL] );
    
}

- (void) addExifData; {
    if(![self exif]){
        return;
    }
    
    NSMutableDictionary *exif_data = [NSMutableDictionary dictionary];
    NSEnumerator *exif_enum = [[self exif] objectEnumerator];
    NSDictionary *elem;
    
    while(elem = [exif_enum nextObject]){
        //format the label, into an proper exif key
        NSMutableString *label = [NSMutableString stringWithString:[elem valueForKey: @"_label"]];

        //remove all ' and ' character
        [label replaceOccurrencesOfString:@" and "
                               withString:@""
                                  options:nil
                                    range:NSMakeRange(0,[label length])];
        
        //remove all space character
        [label replaceOccurrencesOfString:@" "
                               withString:@""
                                  options:nil
                                    range:NSMakeRange(0,[label length])];
        
        //remove all ( character
        [label replaceOccurrencesOfString:@"("
                               withString:@""
                                  options:nil
                                    range:NSMakeRange(0,[label length])];
        
        //remove all ) character
        [label replaceOccurrencesOfString:@")"
                               withString:@""
                                  options:nil
                                    range:NSMakeRange(0,[label length])];        

        //remove all - character
        [label replaceOccurrencesOfString:@"-"
                               withString:@""
                                  options:nil
                                    range:NSMakeRange(0,[label length])];

        if([exif_data valueForKey: [[[NSString stringWithString:[elem valueForKey: @"_tagspace"]] 
                                                    stringByAppendingString:@"_"] 
                                                        stringByAppendingString:label]]){
            continue; // no duplicates
        }        
        
        NSMutableString *raw_value;

        raw_value = [NSMutableString stringWithString: [elem valueForKeyPath:@"raw.$"]];

        /*
        [raw_value replaceOccurrencesOfString:@"/"
                                   withString:@" "
                                      options:nil
                                        range:NSMakeRange(0,[raw_value length])];
        */
        [exif_data setValue: raw_value forKey: [[[NSString stringWithString:[elem valueForKey: @"_tagspace"]] 
                                                    stringByAppendingString:@"_"] 
                                                        stringByAppendingString:label]];
    }
    
    NSMutableDictionary *exifDict = [NSMutableDictionary dictionary];
    NSMutableDictionary *tiffDict = [NSMutableDictionary dictionary];
    
    // make
    [tiffDict setValue:[exif_data valueForKey:@"TIFF_Make"] 
                forKey: (NSString *) kCGImagePropertyTIFFMake];

    // model
    [tiffDict setValue:[exif_data valueForKey: @"TIFF_Model"]
                forKey: (NSString *) kCGImagePropertyTIFFModel];
    
    // copyright
    [tiffDict setValue:[exif_data valueForKey:@"TIFF_CopyRight"]
                forKey: (NSString *) kCGImagePropertyTIFFCopyright];
    
    // x-resolution
    [tiffDict setValue: [self getNumberFrom: [exif_data valueForKey:@"TIFF_XResolution"]]
                forKey: (NSString *) kCGImagePropertyTIFFXResolution];
    
    // y-resolution
    [tiffDict setValue: [self getNumberFrom:[exif_data valueForKey:@"TIFF_YResolution"]]
                forKey: (NSString *) kCGImagePropertyTIFFYResolution];
    
    // resolution unit
    [tiffDict setValue: [NSNumber numberWithInt: [[exif_data valueForKey:@"TIFF_ResolutionUnit"] intValue]]
                forKey: (NSString *) kCGImagePropertyTIFFResolutionUnit];    
    
    // iso
    [exifDict setValue: [NSNumber numberWithShort: (short) [[exif_data valueForKey:@"EXIF_ISOSpeed"] intValue]]
                forKey:(NSString *) kCGImagePropertyExifISOSpeedRatings];
    
    // aperture
    [exifDict setValue: [self getNumberFrom: [exif_data valueForKey:@"EXIF_Aperture"]]
                                        forKey: (NSString *) kCGImagePropertyExifApertureValue];
    
    // shutter speed
    [exifDict setValue: [self getNumberFrom: [exif_data valueForKey: @"EXIF_ShutterSpeed"]]
                forKey: (NSString *) kCGImagePropertyExifShutterSpeedValue];

    // exposure program
    [exifDict setValue: [NSNumber numberWithInt: [[exif_data valueForKey: @"EXIF_ExposureProgram"] intValue]]
                                        forKey: (NSString *) kCGImagePropertyExifExposureProgram];

    // exposure bias value
    [exifDict setValue: [self getNumberFrom: [exif_data valueForKey: @"EXIF_ExposureBias"]]
                forKey: (NSString *) kCGImagePropertyExifExposureBiasValue];
    
    // Date and time (original)
    [exifDict setValue: [exif_data valueForKey: @"EXIF_DateTimeOriginal"]
                forKey: (NSString *) kCGImagePropertyExifDateTimeOriginal];
    
    // Date and time (digitized)
    [exifDict setValue: [exif_data valueForKey:@"EXIF_DateTimeDigitized"]
                forKey:(NSString *) kCGImagePropertyExifDateTimeDigitized];
    
    // flash
    [exifDict setValue: [NSNumber numberWithInt: [[exif_data valueForKey: @"EXIF_Flash"] intValue]]
                                        forKey: (NSString *) kCGImagePropertyExifFlash];

    // color space
    [exifDict setValue: [NSNumber numberWithInt: [[exif_data valueForKey: @"EXIF_ColorSpace"] intValue]]
                forKey: (NSString *) kCGImagePropertyExifColorSpace];
    
    // focal length
    [exifDict setValue: [self getNumberFrom: [exif_data valueForKey: @"EXIF_FocalLength"]]
                forKey: (NSString *) kCGImagePropertyExifFocalLength];
    
    // exposure mode
    [exifDict setValue: [NSNumber numberWithInt: [[exif_data valueForKey: @"EXIF_ExposureMode"] intValue]]
                forKey: (NSString *) kCGImagePropertyExifExposureMode];
    
    // metering
    [exifDict setValue: [NSNumber numberWithInt: [[exif_data valueForKey: @"EXIF_MeteringMode"] intValue]]
                forKey: (NSString *) kCGImagePropertyExifMeteringMode];
    
    // exposure time
    [exifDict setValue: [self getNumberFrom: [exif_data valueForKey:@"EXIF_Exposure"]]
                                           forKey: (NSString *) kCGImagePropertyExifExposureTime];
    
    // focalplane unit
    [exifDict setValue:[NSNumber numberWithInt:[[exif_data valueForKey:@"EXIF_FocalPlaneResolutionUnit"] intValue]]
                forKey: (NSString *) kCGImagePropertyExifFocalPlaneResolutionUnit];

    // focalplane x resolution
    [exifDict setValue:[self getNumberFrom:[exif_data valueForKey:@"EXIF_FocalPlaneXResolution"]]
                forKey: (NSString *)kCGImagePropertyExifFocalPlaneXResolution];
    
    // focalplane y resolution
    [exifDict setValue: [self getNumberFrom:[exif_data valueForKey:@"EXIF_FocalPlaneYResolution"]]
                forKey: (NSString *)  kCGImagePropertyExifFocalPlaneYResolution];
    
    // version
    [exifDict setValue: @"0220" forKey: (NSString *) kCGImagePropertyExifVersion];
    
    NSURL *file = [NSURL fileURLWithPath: [self downloadPath]];
    
    CGImageSourceRef source = CGImageSourceCreateWithURL( (CFURLRef) file, NULL);
    
    if (!source) {
        NSLog(@"***Could not create image source ***  %@", file);
        return;
    }    
    
    CFStringRef UTI = CGImageSourceGetType(source);

    NSMutableData *data = [NSMutableData data];

    CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)data,UTI,1,NULL);
    
    if(!destination) {
        NSLog(@"***Could not create image destination ***");
        return;
    }
    
    NSMutableDictionary *metaData = [NSMutableDictionary dictionary];
    [metaData setObject: exifDict forKey:(NSString *)kCGImagePropertyExifDictionary];
    [metaData setObject: tiffDict forKey: (NSString *) kCGImagePropertyTIFFDictionary];
    
    //add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
    CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef) metaData);
    
    //tell the destination to write the image data and metadata into our data object.
    //It will return false if something goes wrong
    BOOL success = NO;
    success = CGImageDestinationFinalize(destination);
    
    if(!success) {
        NSLog(@"***Could not create data from image destination ***");
        return;
    }
    
    //now we have the data ready to go, so do whatever you want with it
    //here we just write it to disk at the same path we were passed
    [data writeToFile:[self downloadPath] atomically:YES];
    
    //cleanup
    CFRelease(destination);
    CFRelease(source);
}

-(NSNumber *) getNumberFrom: (NSString *) str {

    NSScanner *scanner = [NSScanner scannerWithString: str];
    int numerator, denominator;
    [scanner scanInt: &numerator];
    [scanner scanString:@"/" intoString: NULL];
    [scanner scanInt: &denominator];
    float result = (float) numerator/denominator;
    NSNumber *nm = [NSNumber numberWithFloat: result];

    return nm;
}

@end
